#ifndef MAINSCHEDULER_H_
#define MAINSCHEDULER_H_

#include "PrinterSpooler.h"
#include "DiskDriver.h"
#include "CalcDispatcher.h"
#define INIT_WALL_CLOCK 0

class MainScheduler {
protected:

	class MapTypeScheduler: public Data {
	protected:
		const int m_key; // map's key
		TaskScheduler& m_Value; // map's value

		/***************************************************************************************
		* function name: MapTypeScheduler(const MapTypeScheduler& mapToCopy)
		* The Input: Map object to be copied
		* The output: None
		* The Function operation: Empty implementation since each scheduler held is unique
		***************************************************************************************/
		MapTypeScheduler(const MapTypeScheduler& mapToCopy): m_key(mapToCopy.m_key), m_Value(mapToCopy.m_Value) { }

	public:
		/***************************************************************************************
		* function name: MapTypeScheduler(const int key, TaskScheduler& mapValue)
		* The Input: Map object's key and reference to task scheduler to be map object's value
		* The output: None
		* The Function operation: Creates a new map object holding given key and value
		***************************************************************************************/
		MapTypeScheduler(const int key,TaskScheduler& mapValue);

		/***************************************************************************************
		* function name: ~MapTypeScheduler()
		* The Input: None
		* The output: None
		* The Function operation: Destructs map object
		***************************************************************************************/
		~MapTypeScheduler();

		/***************************************************************************************
		* function name: bool operator==(const MapTypeScheduler& otherMap) const
		* The Input: Reference to map object to be compared with
		* The output: True if activating object's key is equal to given map's, False if not
		* The Function operation: Compares key attributes of both map objects and returns result.
		* 					      Method does not change the object
		***************************************************************************************/
		bool operator==(const MapTypeScheduler& otherMap) const {return m_key == otherMap.m_key;}

		/***************************************************************************************
		* function name: bool operator==(const int otherKey) const
		* The Input: Key to be compared with
		* The output: True if activating object's key is equal to given key, False if not
		* The Function operation: Compares key attributes of map object with given key and returns
		* 					      result. Method does not change the object
		***************************************************************************************/
		bool operator==(const int otherKey) const {return m_key == otherKey;}

		/***************************************************************************************
		* function name: bool operator>(const MapTypeScheduler& otherMap) const
		* The Input: Reference to map object to be compared with
		* The output: True if activating object's key is greater than given map's, False if not
		* The Function operation: Compares key attributes of both map objects and returns result.
		* 					      Method does not change the object
		***************************************************************************************/
		bool operator>(const MapTypeScheduler& otherMap) const {return m_key > otherMap.m_key;}

		/***************************************************************************************
		* function name: bool operator>(const int otherKey) const
		* The Input: Key to be compared with
		* The output: True if activating object's key is greater than given key, False if not
		* The Function operation: Compares key attributes of map object with given key and returns
		* 					      result. Method does not change the object
		***************************************************************************************/
		bool operator>(const int otherKey) const {return m_key > otherKey;}

		/***************************************************************************************
		* function name: TaskScheduler& getValue() const
		* The Input: None
		* The output: Reference to map object's value
		* The Function operation: Returns map object's value attribute
		***************************************************************************************/
		TaskScheduler& getValue() const {return m_Value;}

		/***************************************************************************************
		* function name: const int getKey() const
		* The Input: None
		* The output: Map object's key
		* The Function operation: Returns map object's key attribute
		***************************************************************************************/
		const int getKey() const {return m_key;} // TODO check if best solution
	};

	class MapLinkedList: public DataLinkedList {
	protected:

		/***************************************************************************************
		* function name: MapLinkedList(const MapLinkedList& listToCopy)
		* The Input: None
		* The output: None
		* The Function operation: Empty implementation since lists are not copied
		***************************************************************************************/
		MapLinkedList(const MapLinkedList& listToCopy): DataLinkedList(listToCopy) { }

	public:
		/***************************************************************************************
		* function name: MapLinkedList()
		* The Input: None
		* The output: None
		* The Function operation: Initializes an empty map object linked list
		***************************************************************************************/
		MapLinkedList();

		/***************************************************************************************
		* function name: ~MapLinkedList()
		* The Input: None
		* The output: None
		* The Function operation: Destructs map linked list object
		***************************************************************************************/
		virtual ~MapLinkedList();

		/***************************************************************************************
		* function name: void internalAdd(MapTypeScheduler& newData, const Iterator& positionHolder)
		* The Input: Reference to map object to be added and reference to an iterator pointing to
		* 		     the node that before it new object will be linked
		* The output: None
		* The Function operation: Adds new object to list and links it before the node give
		* 					      iterator holds
		***************************************************************************************/
		void internalAdd(MapTypeScheduler& newData, const Iterator& positionHolder);

		void print(const int time, const int type); // TODO DEBUG!!!
	};

	unsigned int m_wallClock;
	MapLinkedList m_mapList;
	enum Keys {PRINTER_SPOOLER = 1,
		DISK_DRIVER,
		CALC_DISPATCHER}; // used to select which scheduler to create according to given key

	/***************************************************************************************
	* function name: MainScheduler(const MainScheduler& schedToCopy)
	* The Input: Main scheduler to be copied
	* The output: None
	* The Function operation: Empty implementation since the main scheduler is unique
	***************************************************************************************/
	MainScheduler(const MainScheduler& schedToCopy) { }

	/***************************************************************************************
	* function name: TaskScheduler& createScheduler(const int key)
	* The Input: Key in map that should hold new scheduler
	* The output: Reference to the new scheduler
	* The Function operation: Creates a scheduler that matched given map key and returns
	* 						  a reference to it
	***************************************************************************************/
	TaskScheduler& createScheduler(const int key) const;

public:
	/***************************************************************************************
	* function name: MainScheduler()
	* The Input: None
	* The output: None
	* The Function operation: Initializes a main scheduler object
	***************************************************************************************/
	MainScheduler();

	/***************************************************************************************
	* function name: ~MainScheduler()
	* The Input: None
	* The output: None
	* The Function operation: Destructs main scheduler object
	***************************************************************************************/
	~MainScheduler();

	/***************************************************************************************
	* function name: void addJob(const unsigned int startTime, const unsigned int length, const int priority, const int type)
	* The Input: New job's attributes and its type
	* The output: None
	* The Function operation: Adds a new job with given attributes to the task-scheduler
	* 					      holding jobs of new job's type
	***************************************************************************************/
	void addJob(const unsigned int startTime, const unsigned int length, const int priority, const int type);

	/***************************************************************************************
	* function name: void execute()
	* The Input: None
	* The output: None
	* The Function operation: Executes all jobs held in schedulers
	***************************************************************************************/
	void execute();
};



#endif
